package com.company.cloud.user.modules.app.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.company.cloud.common.asserts.ValidatorUtils;
import com.company.cloud.common.bean.*;
import com.company.cloud.common.constant.BaseConstant;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.redis.service.RedisUtils;
import com.company.cloud.common.redis.utils.CacheExpireUtils;
import com.company.cloud.common.utils.AuthContextUtils;
import com.company.cloud.common.utils.CheckUtils;
import com.company.cloud.common.utils.PasswordUtils;
import com.company.cloud.common.utils.StrSplitUtils;
import com.company.cloud.company.modules.api.response.CompanySimple;
import com.company.cloud.company.modules.api.service.CompanyRemoteService;
//import com.company.cloud.dis.modules.api.models.DistributorModel;
//import com.company.cloud.dis.modules.api.request.DistributorClientAddParam;
//import com.company.cloud.dis.modules.api.service.DisRemoteService;
import com.company.cloud.user.constant.*;
import com.company.cloud.user.modules.app.controller.req.CheckInvitationParam;
import com.company.cloud.user.modules.mgr.controller.req.UserUpdateParam;
import com.company.cloud.user.modules.app.models.UserCompanyItem;
import com.company.cloud.user.modules.app.models.UserCompanyModel;
import com.company.cloud.user.modules.app.service.UserAppService;
import com.company.cloud.user.modules.app.service.UserLoginService;
import com.company.cloud.user.modules.base.entity.*;
import com.company.cloud.user.modules.base.service.*;
import com.company.cloud.user.modules.cache.models.UserInvitationModel;
import com.company.cloud.user.modules.cache.utils.UserConvertUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;

@Service
public class UserAppServiceImpl implements UserAppService{

	@Autowired
	private UserInfoService userInfoService;
	@Autowired
	private UserRoleInfoService userRoleInfoService;
	@Qualifier("companyRemoteServiceImpl")
	@Autowired
	private CompanyRemoteService companyRemoteService;
	@Autowired
	private RedisUtils redisUtils;
	@Autowired
	private UserShareCodeService userShareCodeService;
	@Autowired
	private UserInvitationInfoService userInvitationInfoService;
	@Autowired
	private TeamUserInfoService teamUserInfoService;
	@Autowired
	private UserLoginService userLoginService;
	@Autowired
	private ThirdUserInfoService thirdUserInfoService;
//	@Autowired
//	private DisRemoteService disRemoteService;
	@Autowired
	private DeptInfoService deptInfoService;

	@Override
	public LoginUserInfo update(UserUpdateParam param, LoginSimpleUserInfo userInfo) {
		ValidatorUtils.validate(param);
		LoginUserInfo loginUserInfo= AuthContextUtils.getUserBySimple(userInfo);
		UserInfo user= userInfoService.getById(userInfo.getId());
		BeanUtils.copyProperties(param, user);
		if(!CollectionUtils.isEmpty(param.getUserTags())) {
			user.setUserTags(StrSplitUtils.list2string(param.getUserTags()));
		}
		user.setEdt(LocalDateTime.now());
		user.setEip(userInfo.getIp());
		user.setEman(userInfo.getUserName());
		userInfoService.updateById(user);

		// 获取三方用户登录信息
		ThirdUserInfo thirdUserInfo = thirdUserInfoService.getById(userInfo.getThirdId());
		LoginUserInfo data= userLoginService.login(user, thirdUserInfo, userInfo.getToken(), null);
		return data;
	}

	@Override
	@Transactional
	public void updateWithRole(UserInfo userInfo, UserInvitationInfo userInvitationInfo, LoginSimpleUserInfo loginUserInfo) {
		userInfoService.updateById(UserConvertUtils.getUserInfo(userInvitationInfo, userInfo));
		// 角色关联关系
		Set<String> roles = StrSplitUtils.parse2set(userInvitationInfo.getUserRoles(), String.class);
		if (!CollectionUtils.isEmpty(roles)) {
			List<UserRoleInfo> comUserRoleInfos = new ArrayList<UserRoleInfo>();
			for (String roleCode : roles) {
				if(roleCode!=null && !"".equals(roleCode)) {
					UserRoleInfo userRoleInfo = new UserRoleInfo();
					userRoleInfo.setCompanyNo(userInfo.getCompanyNo());
					userRoleInfo.setUserId(userInfo.getId());
					userRoleInfo.setRoleCode(roleCode);
					if(loginUserInfo!=null) {
						userRoleInfo.addCreateParam(loginUserInfo);
						userRoleInfo.addEditParam(loginUserInfo);
					}else {
						userRoleInfo.setCdt(LocalDateTime.now());
						userRoleInfo.setCip(userInfo.getRegIp());
						userRoleInfo.setCman(userInfo.getId());
						userRoleInfo.setEdt(LocalDateTime.now());
						userRoleInfo.setEip(userInfo.getRegIp());
						userRoleInfo.setEman(userInfo.getId());
					}
					comUserRoleInfos.add(userRoleInfo);
				}
			}
			if(comUserRoleInfos.size()>0) {
				userRoleInfoService.saveBatch(comUserRoleInfos);
			}
		}

		// 如果有邀请，更新邀请信息状态
		if (userInvitationInfo != null && CheckUtils.hasInt(userInvitationInfo.getId())) {
			userInvitationInfoService.update(new UpdateWrapper<UserInvitationInfo>()
					.eq("id", userInvitationInfo.getId())
					.set("invitation_state", InviteStateTypeEnum.CONFIRMED.getCode())
			);
			// 如果有团队邀请，加入团队
			if (InviteTypeEnum.TEAM.getCode().equals(userInvitationInfo.getInvitationType())
					&& CheckUtils.hasInt(userInvitationInfo.getTeamId())) {
					TeamUserInfo teamUserInfo = new TeamUserInfo();
					teamUserInfo.setCompanyNo(userInfo.getCompanyNo());
					teamUserInfo.setTeamId(userInvitationInfo.getTeamId());
					teamUserInfo.setUserId(userInfo.getId());
					teamUserInfo.addCreateParam(loginUserInfo);
					teamUserInfo.addEditParam(loginUserInfo);
					teamUserInfoService.save(teamUserInfo);
			}
		}
		// 更新三方用户表的companyNo
		ThirdUserInfo thirdUserInfo = thirdUserInfoService.getById(loginUserInfo.getThirdId());
		if (!thirdUserInfo.getCompanyNo().equals(userInfo.getCompanyNo())) {
			thirdUserInfo.setCompanyNo(userInfo.getCompanyNo());
			thirdUserInfo.addEditParam(loginUserInfo);
			thirdUserInfoService.updateById(thirdUserInfo);
		}
		// 如果有分销商信息，更新分销商信息
//		BaseClientResult<DistributorModel> dis = disRemoteService.getDistributor(userInfo.getId());
//		if (CheckUtils.hasClientResult(dis) && null != dis.getData()) {
//			DistributorClientAddParam params = new DistributorClientAddParam();
//			params.setDistributorUserId(userInfo.getId());
//			params.setCompanyNo(userInfo.getCompanyNo());
//			params.setParentDisUserId(userInfo.getReferralUserId());
//			params.setClientUserId(loginUserInfo.getId());
//			params.setClientUserIp(loginUserInfo.getIp());
//			disRemoteService.add2editDistributor(params);
//		}
	}

	@Override
	public void updateUserPassword(Integer id, String oldPassword, String newPassword, LoginSimpleUserInfo userInfo) {
		UserInfo entity=this.getUserInfoById(id);
		if (!PasswordUtils.isCorrect(oldPassword, entity.getSalt(), entity.getPassword())) {
			throw new BusinessException(ErrorUserEnum.User_Password_Error);
		}
		String[] passwords= PasswordUtils.getMd5Password(newPassword);
		entity.setPassword(passwords[0]);
		entity.setSalt(passwords[1]);
		entity.addEditParam(userInfo);
		userInfoService.updateById(entity);
	}

	
	@Override
	public UserCompanyModel getUserCompany(String mobile) {
		List<UserInfo> userList=userInfoService.list(new QueryWrapper<UserInfo>()
				.eq("mobile", mobile)
				.eq("user_state", UserStateEnum.NORMAL.getCode())
		);
		if(CollectionUtils.isEmpty(userList)) {
			return null;
		}
		Set<String> companyNos=new HashSet<String>();
		userList.forEach(item->{
			companyNos.add(item.getCompanyNo());
		});
		BaseClientResult<Map<String, CompanySimple>> companySimpleResp= companyRemoteService.getCompanyMapSimple(companyNos);
		if(!BaseReturnEnum.SUCCESS.getCode().equals(companySimpleResp.getCode())){
			throw new BusinessException(companySimpleResp.getCode(),companySimpleResp.getMsg());
		}
		Map<String, CompanySimple> companyMap=companySimpleResp.getData();
		List<UserCompanyItem> data=new ArrayList<UserCompanyItem>();
		userList.forEach(item->{
			UserCompanyItem entity=new UserCompanyItem();
			entity.setId(item.getId());
			entity.setCompanyNo(item.getCompanyNo());
			entity.setNickName(item.getNickName());
			entity.setRealName(item.getRealName());
			entity.setHeadImg(item.getHeadImg());
			entity.setMobile(item.getMobile());
			entity.setCompany(companyMap==null?null:companyMap.get(item.getCompanyNo()));
			data.add(entity);
		});
		
		UserCompanyModel result=new UserCompanyModel();
		if(CollectionUtils.isEmpty(data)) {
			return result;
		}
		result.setCompanys(data);
		result.setToken(IdUtil.fastSimpleUUID());
		redisUtils.set(result.getToken(), mobile, CacheExpireUtils.getExpireMin(30));
		return result;
	}
	
	
	@Override
	public String getMobileByToken(String token, boolean isDel) {
		String mobile = redisUtils.get(token);
		if (StringUtils.isEmpty(mobile)) {
			throw new BusinessException(ErrorUserEnum.VCode_User_Expire);
		}
		if(isDel) {
			redisUtils.delete(token);
		}
		return mobile;
	}

	@Override
	public IPage<UserInvitationModel> getPasswordInvitation(BasePageParam pageParam, LoginSimpleUserInfo loginUserInfo) {
		IPage<UserInvitationInfo> page = userInvitationInfoService.page(
				new Page<>(pageParam.getPage(), pageParam.getRows()),
				new QueryWrapper<UserInvitationInfo>()
						.eq("rows_state",  BaseConstant.EnabledEnum.ENABLED.getCode())
						.eq("company_no", loginUserInfo.getCompanyNo())
						.eq("invitation_user_id", loginUserInfo.getId())
						.eq("invitation_type", InviteTypeEnum.TEAM.getCode())
						.eq("check_type", InviteCheckTypeEnum.Password_Check.getCode())
						.orderByDesc("cdt")
		);
		IPage<UserInvitationModel> data= page.convert(new Function<UserInvitationInfo, UserInvitationModel>() {
			@Override
			public UserInvitationModel apply(UserInvitationInfo entity) {
				return UserConvertUtils.getUserInvitationModel(entity);
			}
		});
		return data;
	}

	@Override
	public UserInvitationModel getPasswordInvitationNew(LoginSimpleUserInfo loginUserInfo) {
		UserInvitationInfo entity = userInvitationInfoService.getOne(new QueryWrapper<UserInvitationInfo>()
				.eq("rows_state",  BaseConstant.EnabledEnum.ENABLED.getCode())
				.eq("company_no", loginUserInfo.getCompanyNo())
				.eq("invitation_user_id", loginUserInfo.getId())
				.eq("invitation_type", InviteTypeEnum.TEAM.getCode())
				.eq("invitation_state", InviteStateTypeEnum.UNCONFIRMED.getCode())
				.and(qw->qw.ge("over_date", LocalDateTime.now()).or().isNull("over_date"))
				.eq("check_type", InviteCheckTypeEnum.Password_Check.getCode())
				.orderByDesc("cdt").last("limit 0, 1"));
		if (null == entity) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		UserInvitationModel model = UserConvertUtils.getUserInvitationModel(entity);
		// 获取其他展示信息
		if (CheckUtils.hasInt(entity.getDeptId())) {
			DeptInfo dept = deptInfoService.getById(entity.getDeptId());
			if (null != dept) {
				model.setDeptName(dept.getName());
			}
		}
		return model;
	}

	@Override
	public UserInvitationModel getPasswordInvitationById(Integer id) {
		UserInvitationInfo entity = userInvitationInfoService.getOne(new QueryWrapper<UserInvitationInfo>()
				.eq("rows_state",  BaseConstant.EnabledEnum.ENABLED.getCode())
				.eq("id", id)
				.eq("invitation_state", InviteStateTypeEnum.UNCONFIRMED.getCode())
				.and(qw->qw.ge("over_date", LocalDateTime.now()).or().isNull("over_date")));
		if (null == entity) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		UserInvitationModel model = UserConvertUtils.getUserInvitationModel(entity);
		// 获取其他展示信息
		BaseClientResult<CompanySimple> companySimpleResp=
				companyRemoteService.getCompanySimple(model.getCompanyNo());
		if(BaseReturnEnum.SUCCESS.getCode().equals(companySimpleResp.getCode()) &&
				null != companySimpleResp.getData()){
			model.setCompanyName(companySimpleResp.getData().getName());
		}

		if (CheckUtils.hasInt(entity.getDeptId())) {
			DeptInfo dept = deptInfoService.getById(entity.getDeptId());
			if (null != dept) {
				model.setDeptName(dept.getName());
			}
		}
		return model;
	}

	@Override
	public UserInfo checkInvitation(CheckInvitationParam param, LoginSimpleUserInfo loginUserInfo) {
		UserInfo userInfo = userInfoService.getById(loginUserInfo.getId());
		if (null == userInfo) {
			throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
		}
		UserInvitationInfo userInvitationInfo = userInvitationInfoService.getById(param.getId());
		if (null == userInvitationInfo ||
				! InviteStateTypeEnum.UNCONFIRMED.getCode().equals(userInvitationInfo.getInvitationState()) ||
				! userInvitationInfo.getOverDate().isAfter(LocalDateTime.now())) {
			throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
		}
		if (InviteCheckTypeEnum.Mobile_Check.getCode().equals(param.getCheckType())) {
			if (CheckUtils.isEmpty(param.getCheckMobile()) ||
					! param.getCheckMobile().equals(userInvitationInfo.getCheckMobile()) ||
					! param.getCheckMobile().equals(userInfo.getMobile())) {
				throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
			}
		} else if (InviteCheckTypeEnum.Password_Check.getCode().equals(param.getCheckType())) {
			if (CheckUtils.isEmpty(param.getCheckPassword()) ||
					! userInvitationInfo.getInvitationUserId().equals(userInfo.getId())) {
				throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
			}
		} else {
			throw new BusinessException(BaseReturnEnum.PARAM_ERROR);
		}

		userInfoService.updateById(UserConvertUtils.getUserInfo(userInvitationInfo, userInfo));
		// 更新邀请状态
		userInvitationInfoService.update(new UpdateWrapper<UserInvitationInfo>()
				.eq("id", userInvitationInfo.getId())
				.set("invitation_state", InviteStateTypeEnum.CONFIRMED.getCode())
		);
		// 如果有团队邀请，加入团队
		if (CheckUtils.hasInt(userInvitationInfo.getTeamId())) {
			if (teamUserInfoService.count(new QueryWrapper<TeamUserInfo>().eq("user_id", userInfo.getId())) < 1) {
				TeamUserInfo teamUserInfo = new TeamUserInfo();
				teamUserInfo.setCompanyNo(userInvitationInfo.getCompanyNo());
				teamUserInfo.setTeamId(userInvitationInfo.getTeamId());
				teamUserInfo.setUserId(userInfo.getId());
				teamUserInfo.addCreateParam(loginUserInfo);
				teamUserInfo.addEditParam(loginUserInfo);
				teamUserInfoService.save(teamUserInfo);
			}
		}
		return userInfo;
	}


	@Override
	public void updateMobile(Integer id, String mobile, LoginSimpleUserInfo userInfo) {
		UserInfo entity=this.getUserInfoById(id);
		//todo 未实现
	}


	@Override
	public LoginUserInfo updateShareCode(LoginSimpleUserInfo userInfo) {
		LoginUserInfo loginUserInfo= AuthContextUtils.getUserBySimple(userInfo);
		UserInfo entity = userInfoService.getById(userInfo.getId());
		entity.setShareCode(IdUtil.getSnowflake(2, 2).nextIdStr());
		entity.setEdt(LocalDateTime.now());
		entity.setEip(userInfo.getIp());
		entity.setEman(userInfo.getUserName());
		userInfoService.updateById(entity);
		//分享码
		UserShareCode shareCodeEntity=new UserShareCode();
		shareCodeEntity.setCompanyNo(entity.getCompanyNo());
		shareCodeEntity.setUserId(entity.getId());
		shareCodeEntity.setShareCode(entity.getShareCode());
		shareCodeEntity.addEditParam(userInfo);
		userShareCodeService.save(shareCodeEntity);

		ThirdUserInfo thirdUserInfo = thirdUserInfoService.getById(userInfo.getThirdId());
		LoginUserInfo data= userLoginService.login(entity, thirdUserInfo, userInfo.getToken(), null);
		return data;
	}

	private UserInfo getUserInfoById(Integer id) {
		UserInfo entity = userInfoService.getById(id);
		if (null == entity ) {
			throw new BusinessException(ErrorUserEnum.User_Info_Null);
		}
		if(!UserStateEnum.NORMAL.getCode().equals(entity.getUserState())) {
			throw new BusinessException(ErrorUserEnum.User_Info_Null);
		}
		return entity;
	}









	
}
